#pragma once

#include <algorithm>
#include <jsoncpp/json/json.h>
#include "index.hpp"
#include <unordered_map>
#include <vector>



namespace ns_search
{
    class Searcher
    {
    private:
        ns_index::Index* index;

    public:
        Searcher()
        {}
        
        ~Searcher()
        {}

        struct InvertedNodePrint
        {
            uint64_t doc_id;    
            int weight;
            std::vector<std::string> words;
        };

        void InitSearcher(const std::string path)
        {
            // 获取 index 单例
            index = ns_index::Index::GetInstance();
            LOG(INFO, "获取单例对象成功");

            // 根据index 对象构建索引
            index->BuildIndex(path);
        }

        // static bool cmp(const ns_index::InvertedNode& a, const ns_index::InvertedNode& b)
        // {
        //     return a.weight > b.weight;
        // }

        static bool cmp(const InvertedNodePrint& a, const InvertedNodePrint& b)
        {
            return a.weight > b.weight;
        }

        // 根据用户提供的语句进行搜索
        void search(const std::string& query, std::string& ret_josn)
        {
            // 对用户的输入进行分词
            std::vector<std::string> words;
            ns_util::Cut::CutText(query, words);
            // 进行倒排索引
            // ns_index::Index::InvertedList inverted_list;

            std::vector<InvertedNodePrint> inverted_list;
            std::unordered_map<uint64_t, InvertedNodePrint> mp;

            for(auto& word : words)
            {
                // 获取 关键字word 对应的倒排拉链
                ns_index::Index::InvertedList* tmp = nullptr;
                
                tmp = index->GetInvertedList(word);
                if(nullptr == tmp)
                    continue;
                
                // // 汇总
                // inverted_list.insert(inverted_list.begin(), tmp->begin(), tmp->end());

                for(const auto& elem : *tmp)
                {
                    auto& item = mp[elem.doc_id];
                    item.doc_id = elem.doc_id;
                    item.weight += elem.weight;
                    item.words.push_back(elem.word);
                }

            }

            // 遍历去重之后的mp
            for(auto& ch : mp)
            {
                inverted_list.push_back(std::move(ch.second));
            }

            if(inverted_list.size() == 0)
            {
                ret_josn = "未找到相应文档";
                LOG(WARNING, "未找到相应文档");
                return;
            }

            // 进行汇总 按权重排序
            // sort(inverted_list.begin(), inverted_list.end(), 
            // [](ns_index::InvertedNode& a, ns_index::InvertedNode& b) 
            // { return a.weight > b.weight; } );
            sort(inverted_list.begin(), inverted_list.end(), cmp);

            // josn 串返回
            Json::Value root;
            for(auto& doc : inverted_list)
            {
                ns_index::ForwardNode* tmp = index->GetForwardIndex(doc.doc_id);
                if(nullptr == tmp)
                    continue;

                Json::Value item;
                item["title"] = tmp->title;
                item["desc"] = index->GetDescription(doc.words[0], tmp->content);
                // item["id"] = (int)tmp->doc_id;
                // item["weight"] = doc.weight;
                item["url"] = tmp->url;
                root.append(item);
            }
            Json::StyledWriter writer;

            ret_josn = writer.write(root);
        }
    };
}